/*=========================================================================
 Copyright (c) 2008, Nokia Corporation and/or its subsidiary(-ies).
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Nokia Corporation and/or its subsidiary(-ies)nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=========================================================================================*/

#ifndef __NCVIMAGE_H__
#define __NCVIMAGE_H__

#include <e32base.h>
#include <fbs.h>
#include "ncvImageOp.h"
#include "ncvErrors.h"

#define M_PI			3.14159265358979323846
#define SHIFT_FACTOR	10
#define PI				3.14159265
#define FP(s) ( (s)<<SHIFT_FACTOR )
#define RFP(s) ( (s) * 1024)  // 2^SHIFT_FACTOR
#define DEC(s) ( (s) >> SHIFT_FACTOR)
#define MUL(x,y) ( ((y) * (x)) >> SHIFT_FACTOR )
#define DIV(x,y) ( ((x) << SHIFT_FACTOR) / (y) )

#define GETA(rgb) ((TUint8)((rgb)>>24)&0xFF)
#define GETR(rgb) ((TUint8)((rgb)>>16)&0xFF)
#define GETG(rgb) ((TUint8)(((TUint16)(rgb)) >> 8)&0xFF)
#define GETB(rgb) ((TUint8)(rgb))
#define RGB(r,g,b) ((r<<16)|(g<<8)|b)
#define BGR(r,g,b) ((b<<16)|(g<<8)|r)		// Same format as TRgb
#define ARGB(a,r,g,b) ( (a<<24)|(r<<16)|(g<<8)|b)) )
#define RGB_565(r, g, b) (((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3))   // 16bit
#define RGB_444(r, g, b) (((r >> 4) << 8) + ((g >> 4) << 4) + (b >> 4))   // 12bit


class CNokiaCVImage;

/**
 * \enum TImageType
 * \brief CNokiaCVImage type
 * Possible values are:
 *	- ERgbColor
 *	- EGrayScale
 *	- EBw
 * \note Symbian TClass.
 */
enum TImageType
	{
	ERgbColor = 0,
		    EGrayScale,
		    EBw
	};

/**
 * \enum TChannel
 * Enumeration for different color channels for CNokiaCVImages.
 *
 * Valid values are:
 *	- EGrayChannel
 *	- ERedChannel
 *	- EGreenChannel
 *	- EBlueChannel
 *	- EAllChannels (not supported by all operations)
 * \note Symbian TClass.
 */
enum TChannel
	{
	EGrayChannel,
	ERedChannel,
	EGreenChannel,
	EBlueChannel,
	EAllChannels
	};

enum TColorSpace
	{
	EColorSpaceRgb,
	EColorSpaceYuv,
	EColorSpaceHsv,
	EColorSpaceLab,
	EColorSpaceLAlphaBeta,
	EColorSpaceLms,
	EColorSpaceXyz
	};

/**
 * \enum TDirection
 * \brief Direction of the operation.
 *
 * Valid values are:
 *	- EHorizontal
 *	- EVertical
 * \note Symbian TClass.
 */
enum TDirection
	{
	EHorizontal,
	EVertical
	};

class TColorModel
{}
;

/**
 * \class CRgbColorModel
 * \brief RGB color model value
 * \note Symbian TClass.
 */
class CRgbColorModel : public TColorModel
	{
public:
	/**
	 * \var iR
	 * \brief
	 */
	TInt iR;
	/**
	 * \var iG
	 * \brief
	 */
	TInt iG;
	/**
	 * \var iB
	 * \brief
	 */
	TInt iB;
	};

/**
 * \class CYuvColorModel
 * \brief YUV color model value
 * \note Symbian TClass.
 */
class CYuvColorModel : public TColorModel
	{
public:
	/**
	 * \var iY
	 * \brief
	 */
	TInt iY;
	/**
	 * \var iU
	 * \brief
	 */
	TInt iU;
	/**
	 * \var iV
	 * \brief
	 */
	TInt iV;
	};

/**
 * \class CHsvColorModel
 * \brief HSV color model value.
 * \note Symbian TClass.
 */
class CHsvColorModel : public TColorModel
	{
public:
	/**
	 * \var iH
	 * \brief Hue-component, value range: 0.0-360.0
	 */
	TReal iH;
	/**
	 * \var iS
	 * \brief Saturation-component, value range: 0-255
	 */
	TReal iS;
	/**
	 * \var iV
	 * \brief Value-component, value range: 0-255
	 */
	TReal iV;
	};

/**
 * \class CLabColorModel
 * \brief CIE Lab color model value
 * \note Symbian TClass.
 */
class CLabColorModel : public TColorModel
	{
public:
	/**
	 * \var iL
	 * \brief
	 */
	TReal iL;
	/**
	 * \var iA
	 * \brief
	 */
	TReal iA;
	/**
	 * \var iB
	 * \brief
	 */
	TReal iB;
	};

/**
 * \class CXyzColorModel
 * \brief XYZ color model value
 * \note Symbian TClass.
 */
class CXyzColorModel : public TColorModel
	{
	public:

	/**
	 * \var iX
	 * \brief
	 */
	TInt iX;

	/**
	 * \var iY
	 * \brief
	 */

	TInt iY;

	/**
	 * \var iZ
	 * \brief
	 */
	TInt iZ;
	};

/**
 * \class CLmsColorModel
 * \brief LMSb color model value
 * \note Symbian TClass.
 */
class CLmsColorModel : public TColorModel
	{
public:

	/**
	 * \var iL
	 * \brief
	 */
	TReal iL;

	/**
	 * \var iM
	 * \brief
	 */

	TReal iM;

	/**
	 * \var iS
	 * \brief
	 */
	TReal iS;
	};

/**
 * \class CPixelColorModel
 * \brief
 * \note Symbian TClass.
 */
class CPixelColorModel
	{
public:
	/**
	 * Constructor.
	 * \param aRgb TUint32 rgb-value
	 */
	IMPORT_C CPixelColorModel( const TUint32 aRgb );

	/**
	 * Constructor.
	 * \param aRgb TRgb rgb-value
	 */
	IMPORT_C CPixelColorModel( TRgb aRgb );

	/**
	 * Get the red component
	 * \return TUint8 Red-component
	 */
	IMPORT_C TUint8 Red();

	/**
	 * Get the green component
	 * \return TUint8 Green-component
	 */
	IMPORT_C TUint8 Green();

	/**
	 * Get the blue component
	 * \return TUint8 Blue-component
	 */
	IMPORT_C TUint8 Blue();

	/**
	 * Get the value as grayscale
	 * \return TUint8 Grayscale value
	 */
	IMPORT_C TUint8 Gray();

	/**
	 * Convert to YUV
	 * \return CYuvColorModel
	 */
	IMPORT_C CYuvColorModel ToYUV();

	/**
	 * Convert to HSV
	 * \return CHsvColorModel
	 */
	IMPORT_C CHsvColorModel ToHSV();

	/**
	 * Convert to Lab
	 * \return CLabColorModel
	 */
	IMPORT_C CLabColorModel ToLAB();

	/**
	 * Convert to LAlphaBeta
	 * \return CLabColorModel
	 */
	IMPORT_C CLabColorModel ToLAlphaBeta();

	/**
	 * Convert to CIE XYZ
	 * \return CXyzColorModel
	 */
	IMPORT_C CXyzColorModel ToXYZ();

	/**
	 * Convert to LMS
	 * \return CLmsColorModel
	 */
	IMPORT_C CLmsColorModel ToLMS();

	/**
	 * Get RGB value
	 * \return TUint32 RGB-value
	 */
	IMPORT_C TUint32 GetRgb();

	/**
	 * \brief Get RGB value
	 * \return TRgb RGB-value
	 */
	IMPORT_C TRgb GetTRgb();


	/**
	 * \brief Convert image to another colorspace.
	 * \param aImage Image to convert
	 * \param retImg Image converted to another colorspace
	 * \param aColorspace Colorspace to convert to.
	 *
	 * Notice that after conversion the images pixel data is in another colorspace and
	 * you may not be able to draw the image on the screen.
	 *
	 */
	IMPORT_C static void ConvertToColorSpace(CNokiaCVImage* aImage, CNokiaCVImage* retImg, TColorSpace aColorspace);
private:
	TUint32 iRgb;
	};

class CPixelAccess;

/**
 * CPixelAccess class provides access to CNokiaCVImage on a pixel-level. Derived from TBitmapUtil.
 * The usage pattern of CPixelAccess is NOT the same as TBitmapUtil.
 * Begin(), End() calls are included in constructor and destructor.
 *
 * 
 *  
 * Example:
 * <pre>
 * 	CPixelAccess* out = CPixelAccess::NewL(aTarget);
 *	CPixelAccess* in = CPixelAccess::NewL(iImage, out);
 *  ...
 *	in->SetPos( TPoint( rotX, rotY ) );
 *	out->SetPos(TPoint( x, y ) );
 *	out->SetRGB( in->GetRGB() ); // set pixel value from in to out 
 *  ...
 *	delete out;
 *	delete in;
 *
 * </pre> 
 */
class CPixelAccess : public TBitmapUtil
	{
public:
	
	/**
	 * \brief Constructor. Sets the current pixel position to (0,0) position and locks the heap.
	 * NewL() pushes the CPixelAccess object to the CleanUpStack, so you must pop it before delete.
	 * \param aImage CNokiaCVImage to get pixel access to
	 * \note this function can leave (NewLC)
	 * 
	 *	Usage:
	 * <pre>
	 *		CPixelAccess* pa = CPixelAccess::NewLC(iBitmap);
	 *		// do something
	 *		CleanupStack::Pop(pa);
	 *		delete pa;
	 * </pre>
	 * 
	 */
	IMPORT_C static CPixelAccess* NewLC( CNokiaCVImage* aImage );

	/**
	* 
	* \brief Construct a CPixelAccess object with a bitmap and a reference to another pixel access object
	* Typically used when going simultaneously through two bitmaps, e.g. copying pixels from source to target
	* corresponding with TBitmapUtil::Begin(point, anotherBitmapUtil);
	* Sets the current pixel position to (0,0).
	* NewL() pushes the CPixelAccess object to the CleanUpStack, so you must pop it before delete.
	* \param aPixelAccess another aPixelAccess object that is used simultaneously
	* \param aImage CNokiaCVImage to get pixel access to
	* \note this function can leave (NewLC)
	*/ 
	IMPORT_C static CPixelAccess* NewLC( CNokiaCVImage* aImage, CPixelAccess* aPixelAccess );

	/**
	 * \brief Constructor. Sets the current pixel position to (0,0) position and locks the heap.
	 * \param aImage CNokiaCVImage to get pixel access to
	 * NewL() pops the CPixelAccess object from the CleanUpStack. You do not need to use CleanUpStack.
	 * \note this function can leave (NewL)
	 *
	 *	Usage:
	 * 	<pre>
	 *		CPixelAccess* pa = CPixelAccess::NewL(iBitmap);
	 *		// do something
	 *		delete pa;
	 * </pre>
	 *
	 */
	IMPORT_C CPixelAccess* CPixelAccess::NewL( CNokiaCVImage* aImage );

	/**
	* 
	* \brief Construct a CPixelAccess object with a bitmap and a reference to another pixel access object
	* Typically used when going simultaneousl through two bitmps, e.g. copying pixels from source to target
	* corresponding with TBitmapUtil::Begin(point, anotherBitmapUtil);
	* Sets the current pixel position to (0,0).
	* NewL() pops the CPixelAccess object from the CleanUpStack. You do not need to use CleanUpStack.
	* \param aPixelAccess another aPixelAccess object that is used simultaneously
	* \param aImage CNokiaCVImage to get pixel access to
	* \note this function can leave (NewL)
	*/
	IMPORT_C CPixelAccess* CPixelAccess::NewL( CNokiaCVImage* aImage, CPixelAccess* aPixelAccess );


	IMPORT_C virtual ~CPixelAccess();

	/**
	* \brief Return pixel from the current position as a RGB.
	* \return TUint32 RGB value in format used by TRgb: 0x00BBGGRR
	*/
	IMPORT_C TUint32 GetRGB();

	/**
	* \brief Set pixel to the current position.
	* \param aPixel RGB value as TUint32 in format used by TRgb: 0x00BBGGRR
	*/
	IMPORT_C void SetRGB( TUint32 aPixel );

	// Getters for the current pixel in other color spaces
	IMPORT_C CYuvColorModel GetAsYUV();
	IMPORT_C CHsvColorModel GetAsHSV();
	IMPORT_C CLabColorModel GetAsLab();
	IMPORT_C CLabColorModel GetAsLAlphaBeta();
	IMPORT_C CXyzColorModel GetAsXYZ();
	IMPORT_C CLmsColorModel GetAsLMS();

protected:
	/// Protected constructor
	//CPixelAccess( CFbsBitmap* aBitmap );
	CPixelAccess( CNokiaCVImage* aImage );
	/**
	 * \brief Constructor.
	 * \param aImage CNokiaCVImage to get pixel access to
	 */
	CPixelAccess();

	/**
	*	Second-phase constructor.
	*/
	void ConstructL();

private:
	CNokiaCVImage* 	iImage;  // does not own
	TDisplayMode	iDispMode;
	};


/**
 * \class CNokiaCVImage
 * \brief A bitmap image class. Uses CFbsBitmap as an underlying implementation.
 *
 * CNokiaCVImage is a wrapper for CFbsBitmap that is provided by the platform.
 * This class provides DisplayMode independent access to the pixel data,
 * The user of the library does not need to take care of the bit depth conversions.
 *
 * Usage examples (see example applications for more examples):
 *
 * <pre>
 *  // load from file
 *	CNokiaCVImage* incvBitmap = CNokiaCVImage::NewL();
 * 	TRAPD(err1, incvBitmap->CreateL( *aImageFullName ));
 *  ...
 *  // draw bitmap
 *  CWindowGc& gc = SystemGc();
 *  gc.BitBlt( TPoint( 0,0 ), incvBitmap->Bitmap() );
 * </pre>
 *
 */
class CNokiaCVImage : public CBase
	{
public:

	/**
	* \brief Factory method for creating an instance.
	*
	*	Implements two-phase construction functions (NewL(), ConstructL()) to create a new instance
	*	of the object.
	*
	*	Creates new uninitialized image instance.
	* \return CNokiaCVImage*
	*/
	IMPORT_C static CNokiaCVImage* NewL();
	
	/**
	* \brief Factory method for creating an instance.
	*
	*	Implements two-phase construction functions (NewLC(), ConstructL()) to create a new instance
	*	of the object.
	*
	*	Creates new uninitialized image instance.
	* \return CNokiaCVImage*
	*/	
	IMPORT_C static CNokiaCVImage* NewLC();

	/**
	* \brief Destructor
	*/
	IMPORT_C virtual ~CNokiaCVImage();

	/**
	* \brief Create image from a file.
	* \param aFileName
	* \note the function can leave
	*/
	IMPORT_C void CreateL( const TDesC& aFileName );

	/**
	* \brief Create image from CFbsBitmap. Ownership is moved.
	* \param aBitmap
	* \note the function can leave
	*/
	IMPORT_C void CreateL( CFbsBitmap& aBitmap );

	/**
	* \brief Create empty image with given size.
	* \param aSize
	* \param aDisplayMode
	* \note the function can leave
	*/
	IMPORT_C void CreateL( TSize aSize, TDisplayMode aDisplayMode = EColor16M );

	/**
	* \brief Get pointer to the original bitmap, Ownership is not transferred.
	* \return CFbsBitmap*
	*/
	IMPORT_C CFbsBitmap* Bitmap();

	/**
	* \brief Size of the image.
	* \return TSize
	*/
	IMPORT_C TSize Size() const;

	/**
	* \brief Address of the first pixel. Ownership is not transfered.
	* \return TUint32*
	*/
	IMPORT_C TUint32* Ptr() const;


	/**
	 * \brief Return the display mode of this CNokiaCVImage
	 * \return TDisplayMode
	 */
	IMPORT_C TDisplayMode DisplayMode();


	/**
	* \brief Get the RGB value of the specified pixel.
	* \param aColor
	* \param aPixel
	*/
	IMPORT_C void GetPixel( TRgb& aColor, TPoint& aPixel );



	IMPORT_C TColorSpace ColorSpace() const;

	/**
	* \brief Copy a source image to the target image. Source and target images may be of different display modes and sizes.
	* \param aSource CNokiaCVImage to use for source
	* \param aTarget CNokiaCVImage to use for target
	* \param aBlendingRatio A ratio for alpha blending images. An integer between 0 and 100. 
	*  Default value = 100 which copies the source fully over the target.
	* 
	*/
	IMPORT_C static void Copy( CNokiaCVImage* aSource, CNokiaCVImage* aTarget, TInt aBlendingRatio=100 );

	/**
	* \brief Copy a source image to the target image. Source and target images may be of different display modes and sizes.
	* \param aSource CNokiaCVImage to use for source
	* \param aTarget CNokiaCVImage to use for target
	* \param aSubregion A rectangular subregion of the source image to copy. (i.e. crops the image)
	* \param aTargetPoint A top-left point in target image to copy the subregion to.
	* \param aBlendingRatio A ratio for blending images. An integer between 0 and 100. Value 100 means normal copy with no transparency.
	*/
	IMPORT_C static void Copy( CNokiaCVImage* aSource, CNokiaCVImage* aTarget, TRect aSubregion, TPoint aTargetPoint = TPoint(0,0), TInt aBlendingRatio=50 );

	/**
	* \brief Returns the type of the image (bw, grayscale or rgb), This is derived from the DisplayMode
	*/
	IMPORT_C TImageType GetImageType();

protected:

	/**
	* \brief Protected empty constructor. Use factory methods for creation.
	*/
	CNokiaCVImage();

	/**
	* \brief Second-phase constructor.
	*/
	void ConstructL();

	private:
	void SetImageType(TDisplayMode aMode);

	/// Owns: image buffer.
	CFbsBitmap* iInternalBitmap;

	/// Fast pixel access.
	//CPixelAccess iPixelAccess;

	/// Current pixel model.
	TImageType	iImageType;
	TColorSpace	iColorSpace;


	};

#endif
